package javabasics.netty.demo2;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;

/**
 * @Author suxiaoxiao
 * @Date 2019/9/16 1:26
 * @Version 1.0
 */
public class NettyServer {

    public static void main(String[] args) {
        /**
         * bossGroup 相当于老板
         * workerGroup 相当于员工
         *
         * 老板负责接活，接到活后直接扔给员工，由员工来具体处理。
         */
        // 监听端口
        NioEventLoopGroup bossGroup = new NioEventLoopGroup();
        // 处理每一条连接的数据读写的线程组
        NioEventLoopGroup workerGroup = new NioEventLoopGroup();

        // 引导类
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        serverBootstrap
                // 配置线程组
                .group(bossGroup, workerGroup)
                // 指定 IO模型 为 NIO
                // BIO 这里配置为 OioServerSocketChannel.class
                .channel(NioServerSocketChannel.class)
                // 是否开启 TCP 心跳机制
                .childOption(ChannelOption.SO_KEEPALIVE, true)
                /**
                 * 是否开启 Nagle算法
                 * 如果要求高实时性，有数据发送时就马上发送，则关闭。
                 * 如果需要减少发送次数减少网络交互，就开启。
                 */
                .childOption(ChannelOption.TCP_NODELAY, true)
                // 每条连接的数据读写，具体的逻辑处理。
                .childHandler(new ChannelInitializer<NioSocketChannel>() {
                    @Override
                    protected void initChannel(NioSocketChannel nioSocketChannel) {
                        System.out.println("服务端启动中");
                        // 指定连接数据读写逻辑
                        nioSocketChannel
                                .pipeline()
                                .addLast(new FirstServerHandler());
                    }
                });

        bind(serverBootstrap, 8090);

    }

    /**
     * 绑定端口启动
     * 还可以添加绑定事件
     * bind() 本身是个 future
     */
    private static void bind(final ServerBootstrap serverBootstrap, final int port) {
        serverBootstrap.bind(port).addListener(future -> {
            if (future.isSuccess()) {
                System.out.println("端口绑定成功！");
            } else {
                System.out.println("端口绑定失败！");
                bind(serverBootstrap, port + 1);
            }
        });
    }

}
